“成员AutoSync失败”使用TPT,查看而不是插入触发器

时间:2011-06-02 08:13:26

标签: .net linq linq-to-sql

尝试使用类似于此的TPT模式使用Linq2SQL和类继承http://blogs.msdn.com/sbajaj/archive/2008/04/02/tpt-with-linq-to-sql.aspx

示例应用程序正常工作。这是我的代码:

表和视图:

CREATE TABLE [dbo].[social_event](
    [Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [Creator] [uniqueidentifier] NOT NULL FOREIGN KEY REFERENCES [dbo].[aspnet_Users](UserId),
    [EventDate] [datetime] NOT NULL)
GO

CREATE TABLE [dbo].[social_addfriendevent](
    [ID] [int] NOT NULL PRIMARY KEY FOREIGN KEY REFERENCES [dbo].[social_event](Id),
    [Friend] [uniqueidentifier] NOT NULL FOREIGN KEY REFERENCES [dbo].[aspnet_Users](UserId),
    [Added] [bit] NOT NULL DEFAULT((0)))
GO

CREATE VIEW [dbo].[event]
AS
SELECT t0.Id, t0.Creator, t0.EventDate, t1.Friend, t1.Added, 'AddFriendEvent' AS EventType
FROM  dbo.social_event AS t0 INNER JOIN
   dbo.social_addfriendevent AS t1 ON t0.Id = t1.Id
GO

我的“而不是插入”触发器:

CREATE TRIGGER [dbo].[trigger_update_event] ON [dbo].[event] INSTEAD OF INSERT
AS
    DECLARE @rc AS INT;
    SET @rc = @@ROWCOUNT;
    IF @rc = 0 RETURN;

    DECLARE @Id AS INT
    DECLARE @EventType AS NVARCHAR(50)
    DECLARE @Creator AS uniqueidentifier
    DECLARE @EventDate AS datetime
    DECLARE @Friend AS uniqueidentifier
    DECLARE @Added AS bit 

    IF @rc = 1
        BEGIN
            SELECT @Id=Id,
   @EventType=EventType,
                 @Creator=Creator,
                 @EventDate = getdate(),
                 @Friend=Friend,
                 @Added=Added
            FROM INSERTED

            INSERT INTO dbo.social_event VALUES(@Creator, @EventDate)
            SELECT @Id = SCOPE_IDENTITY()
            IF @EventType = 'AddFriendEvent'
                INSERT INTO dbo.social_addfriendevent VALUES(@Id, @Friend, @Added)                            
        END
    ELSE
        BEGIN
            DECLARE cursor_inserted CURSOR FAST_FORWARD FOR
                SELECT EventType,
                     Creator,
                     EventDate,
                     Friend,
                     Added
                FROM INSERTED
            OPEN cursor_inserted;

            FETCH NEXT FROM cursor_inserted INTO @EventType,
                                             @Creator,
                                             @EventDate,
                                             @Friend,
                                             @Added;
            WHILE @@FETCH_STATUS = 0
            BEGIN
                INSERT INTO dbo.social_event VALUES(@Creator, @EventDate)
                SELECT @Id = SCOPE_IDENTITY()                
                IF @EventType = 'AddFriendEvent'
                INSERT INTO dbo.social_addfriendevent VALUES(@Id, @Friend, @Added)
            END
            CLOSE cursor_inserted;
            DEALLOCATE cursor_inserted;
        END

我的数据类与映射:

[InheritanceMapping(Code = "AddFriendEvent", Type = typeof(AddFriendEvent), IsDefault = true)]
 [Table(Name = "dbo.event")]
 public abstract class Event
 {
 private static int s_id;

 public Event()
 {
  this.Id = --Event.s_id;
 }

 public Event(string eventType)
  : this()
 {
  EventType = eventType;
 }

 [Column(IsPrimaryKey = true)]
 public int Id;

 [Column(Name = "Creator")]
 public Guid CreatorId;

 [Column(Name = "EventDate", DbType = "datetime")] 
 public DateTime Date;

 [Column(IsDiscriminator = true, Name = "EventType")]
 public string EventType;
 }

 public class AddFriendEvent : Event
 {
 [Column(Name = "Added", CanBeNull = false)]
 public bool Added;

 [Column(Name = "Friend", CanBeNull = false)]
 public Guid Friend;

 public AddFriendEvent()
  : base("AddFriendEvent")
 {
 }
 }

当我尝试创建新的“AddFriendEvent”并将其保存到数据库时,如下所示:

DataContext dc = new DataContext(connectionString);
   Table<Event> allEvents = dc.GetTable<Event>();
   AddFriendEvent ev = new AddFriendEvent()
   {
    Added = true,
    CreatorId = Guid.Parse("379959D-58FE-4A57-BB02-559E3E855B8F"),
    Date = DateTime.Now,
    Friend = Guid.Parse("379959D-58FE-4A57-BB02-559E3E855B8F")
   };
   allEvents.InsertOnSubmit(ev);
   dc.SubmitChanges();

“会员AutoSync失败”。怎么了?


3 个答案:

答案 0 :(得分:1)

目前我和我的朋友也有同样的问题。它与LinqtoSQL生成的查询有关。当你使用触发器插入视图时,会发生linq对sql使用的scope_identity的b'coz。

最后从你需要的触发器返回@ID。 B'coz如果不这样做,它会返回NULL并导致问题。

答案 1 :(得分:0)

谢谢,这帮我找到了问题。基本上不要对触发器中的不同表使用任何选择。即使你这样做,只需将select的值赋给触发器中声明的一些变量,这应该可以解决问题。 E.g

        SELECT TOP 1
                @accountStart = def.AccountNoStart, 
                @accountEnd = def.AccountNoEnd,
                @barcode = I.Barcode
        FROM HSBarCodeDefinition def
        INNER JOIN INSERTED I ON def.BarcodeLength = LEN(I.Barcode)     

ID搞砸了,这就是所有问题。

答案 2 :(得分:0)

我遇到了类似的问题,我想分享我的解决方案,因为我花了将近六个小时进行调试。

原来我的一个AFTER INSERT SQL触发器导致了这个System.InvalidOperationException : Member AutoSync异常,但是当我在SSMS中插入相同的记录时没有发生错误。

以下是导致问题的触发器代码:

DECLARE someCursor CURSOR FOR SELECT someIntValue FROM someTable
WHERE someColumn = 1

OPEN someCursor

WHILE (1 = 1)
BEGIN
    FETCH NEXT FROM someCursor

    IF (@@FETCH_STATUS <> 0)
    BREAK

    // For each row, insert into another table
    INSERT INTO AnotherTable (Column1, Column2) VALUES (3,4)
END
CLOSE someCursor
DEALLOCATE someCursor

问题行是FETCH NEXT FROM someCursor - 我没有使用INTO关键字,根据MSDN SQL文档,这不是必需的。

所以我将代码更改为此,我的AutoSync异常消失了。

DECLARE @localVariable int

DECLARE someCursor CURSOR FOR SELECT someIntValue FROM someTable
WHERE someColumn = 1

OPEN someCursor

WHILE (1 = 1)
BEGIN
    FETCH NEXT FROM someCursor INTO @localVariable // MUST ADD THIS

    IF (@@FETCH_STATUS <> 0)
    BREAK

    // For each row, insert into another table
    INSERT INTO AnotherTable (Column1, Column2) VALUES (3,4)
END
CLOSE someCursor
DEALLOCATE someCursor

希望这会有所帮助,因为我遇到了同样的问题。